package controllers

import (
	"log"
	"myapp/config"
	"myapp/dal/model"
	"myapp/dal/query"
	"myapp/pkg"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"
)

type LoginInput struct {
	Username string `json:"username" binding:"required"`
	Password string `json:"password" binding:"required"`
}

type LoginWechatInput struct {
	Iv        string `json:"iv" binding:"required"`
	PhoneData string `json:"phone_data" binding:"required"`
	Openid    string `json:"openid" binding:"required"`
}

func Login(db *gorm.DB) gin.HandlerFunc {
	jwtUtil := pkg.NewJWT(config.Conf.JwtSecret)

	return func(c *gin.Context) {
		var input LoginInput
		if err := c.ShouldBindJSON(&input); err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
			return
		}

		var user model.User
		if err := db.Preload("Role").Where("username = ?", input.Username).First(&user).Error; err != nil {
			c.JSON(http.StatusUnauthorized, gin.H{"error": "用户名或密码错误"})
			return
		}

		/*aa, _ := bcrypt.GenerateFromPassword([]byte("123456"), 10)
		fmt.Println(string(aa))*/

		if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(input.Password)); err != nil {
			c.JSON(http.StatusUnauthorized, gin.H{"error": "用户名或密码错误"})
			return
		}

		token, err := jwtUtil.GenerateToken(uint(user.ID), user.Username, uint(user.RoleID))
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "生成Token失败"})
			return
		}

		log.SetPrefix("[auth]")
		log.Println("登錄成功")

		c.JSON(http.StatusOK, gin.H{
			"token": token,
		})
	}
}

func AuthSession(db *gorm.DB) gin.HandlerFunc {
	jwtUtil := pkg.NewJWT(config.Conf.JwtSecret)

	return func(c *gin.Context) {
		query.SetDefault(db)

		wechat := pkg.Wechat{
			AppId:     config.Conf.WechatAppId,
			AppSecret: config.Conf.WechatAppSecret,
		}

		session, err := wechat.GetSessionKey(c.Query("code"))
		if err != nil {
			c.JSON(http.StatusOK, gin.H{
				"message": err.Error(),
			})
			return
		}

		token := ""
		user := &model.User{}
		if len(session.OpenId) > 0 {
			uc, _ := query.UserWechat.Where(query.UserWechat.Openid.Eq(session.OpenId)).Take()
			if uc == nil {
				uc = &model.UserWechat{
					UserID:     0,
					Openid:     session.OpenId,
					Createtime: time.Now().Unix(),
					SessionKey: session.SessionKey,
				}

				query.UserWechat.Create(uc)
			}

			user, _ = query.User.Where(query.User.ID.Eq(uc.UserID)).Take()
			if user != nil {
				token, err = jwtUtil.GenerateToken(uint(user.ID), user.Username, uint(user.RoleID))
				if err != nil {
					c.JSON(http.StatusInternalServerError, gin.H{"error": "生成Token失败"})
					return
				}
			}
		}

		c.JSON(http.StatusOK, gin.H{
			"key":     session.SessionKey,
			"openid":  session.OpenId,
			"code":    session.ErrCode,
			"message": session.ErrMsg,
			"token":   token,
			"user":    user,
		})
	}
}

func LoginWechat(db *gorm.DB) gin.HandlerFunc {
	jwtUtil := pkg.NewJWT(config.Conf.JwtSecret)
	return func(c *gin.Context) {
		query.SetDefault(db)
		var input LoginWechatInput
		if err := c.ShouldBindJSON(&input); err != nil {
			c.JSON(http.StatusOK, gin.H{"error": err.Error()})
			return
		}

		wechat := pkg.Wechat{
			AppId:     config.Conf.WechatAppId,
			AppSecret: config.Conf.WechatAppSecret,
		}

		uc, _ := query.UserWechat.Where(query.UserWechat.Openid.Eq(input.Openid)).Take()
		if uc == nil {
			c.JSON(http.StatusOK, gin.H{"error": "非法访问"})
			return
		}

		// if uc.UserID > 0 {
		// 	c.JSON(http.StatusOK, gin.H{"error": "非法访问，请使用authSession登录"})
		// 	return
		// }

		phone, err := wechat.DecryptPhoneData(input.PhoneData, uc.SessionKey, input.Iv)
		if err != nil {
			c.JSON(http.StatusOK, gin.H{
				"message": err.Error(),
			})
			return
		}

		u, _ := query.User.Where(query.User.Username.Eq(phone)).Take()
		if u == nil {
			u = &model.User{
				Username: phone,
				Password: phone,
				RoleID:   1,
			}

			query.User.Create(u)
			query.UserWechat.Where(query.UserWechat.Openid.Eq(input.Openid)).Update(query.UserWechat.UserID, u.ID)
		} else if uc.UserID == 0 {
			//换了小程序的情况，openid变了，手机号不变
			query.UserWechat.Where(query.UserWechat.Openid.Eq(input.Openid)).Update(query.UserWechat.UserID, u.ID)
		}

		token, err := jwtUtil.GenerateToken(uint(u.ID), u.Username, uint(u.RoleID))
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "生成Token失败"})
			return
		}

		c.JSON(http.StatusOK, gin.H{
			"code":  0,
			"token": token,
			"user":  u,
		})
	}
}
